/*
 * @FilePath: \VFD_GD32\BSP\src\drv_vfd.c
 * @Description:
 *
 * Copyright (c) 2025 by ${w}, All Rights Reserved.
 */

#include "main.h"

uint32_t VFD_WRITE_BUFF[5];
eGrid_t eGrid;

// G2G3栅格的左边一位
static uint32_t Number_G2G3_Left[] = {
    0x03B80000, // 0
    0x01200000, // 1
    0x03580000, // 2
    0x03680000, // 3
    0x01E00000, // 4
    0x02E80000, // 5
    0x02F80000, // 6
    0x03200000, // 7
    0x03F80000, // 8
    0x03E80000  // 9
};

// G1栅格的左边一位
static uint32_t Number_G1_Left[] = {
    0x01DC0000, // 0
    0x00900000, // 1
    0x01AC0000, // 2
    0x01B40000, // 3
    0x00F00000, // 4
    0x01740000, // 5
    0x017C0000, // 6
    0x01900000, // 7
    0x01FC0000, // 8
    0x01F40000  // 9
};
// G1G2G3G4栅格的右边一位
static uint32_t Number_G1G2G3G4_Right[] = {
    0x0003B800, // 0
    0x00012000, // 1
    0x00035800, // 2
    0x00036800, // 3
    0x0001E000, // 4
    0x0002E800, // 5
    0x0002F800, // 6
    0x00032000, // 7
    0x0003F800, // 8
    0x0003E800  // 9
};

/**
 * @LastEditTime: Do not edit
 * @Description:
 * @return {}
 */
void vfd_init(void)
{
    rcu_periph_clock_enable(RCU_GPIOA); /* 使能GPIOF时钟 */

    /* 设置PA5推挽输出模式 */
    gpio_mode_set(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLDOWN, GPIO_PIN_5);
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_5);
    /* 设置PA6推挽输出模式 */
    gpio_mode_set(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLDOWN, GPIO_PIN_6);
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_6);
    /* 设置PA7推挽输出模式 */
    gpio_mode_set(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLDOWN, GPIO_PIN_7);
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_7);

    /* 全都输出高 */
    DIN(1);
    CLK(1);
    EN(1);
}

/**
 * @LastEditTime: Do not edit
 * @Description: 
 * @param {uint32_t} buf
 * @return {}
 */
void VFD_SendData(uint32_t buf)
{
	uint8_t i;
	uint32_t temp = buf;

    EN(DISABLE);
    CLK(DISABLE);

	temp = temp >> 8;//实际只用到21位，8位对齐；最后8位用到
	for(i = 0; i < 24; i++)
	{
		CLK(DISABLE);
		if(temp & 0x01)
		{
			DIN(VFD_GRID_ON);
		}
		else
		{
			DIN(VFD_GRID_OFF);
		}
		CLK(ENABLE);
		temp = temp >> 1;
	}
	EN(ENABLE);
}

/**
 * @LastEditTime: Do not edit
 * @Description: 
 * @param {uint8_t} Number
 * @param {uint8_t} PBC_EN
 * @param {uint8_t} MP3_EN
 * @return {}
 */
uint32_t VFD_Show_Number_G1(uint8_t Number, uint8_t PBC_EN, uint8_t MP3_EN)
{
	uint8_t L_LCD, R_LCD, sleect;
	uint32_t temp;
	sleect = PBC_EN & 0x01;
	sleect = (sleect << 1 ) | (MP3_EN & 0x01);
	L_LCD = Number / 10;
	R_LCD = Number % 10;
	temp = Number_G1_Left[L_LCD] | Number_G1G2G3G4_Right[R_LCD];
	switch(sleect)
	{
		case 0x00://不显示
			break;
		case 0x01://MP3
			temp = temp | (1 << 25);
			break;
		case 0x02://PBC
			temp = temp | (1 << 26);
			break;
		case 0x03://PBC+MP3
			temp = temp | (3 << 25);
			break;
		default:break;
	}
	return temp;
}

/**
 * @LastEditTime: Do not edit
 * @Description: 
 * @param {uint8_t} Number
 * @param {uint8_t} COLON_EN
 * @param {uint8_t} VD_D_EN
 * @return {}
 */
uint32_t VFD_Show_Number_G2_G3(uint8_t Number, uint8_t COLON_EN, uint8_t VD_D_EN)
{
	uint8_t L_LCD, R_LCD, sleect;
	uint32_t temp;
	sleect = COLON_EN & 0x01;
	sleect = (sleect << 1 ) | (VD_D_EN & 0x01);
	L_LCD = Number / 10;
	R_LCD = Number % 10;
	temp = Number_G2G3_Left[L_LCD] | Number_G1G2G3G4_Right[R_LCD];
	switch(sleect)
	{
		case 0x00://不显示
			break;
		case 0x01://VD_D
			temp = temp | 0x04000000;
			break;
		case 0x02://COLON
			temp = temp | 0x00040000;
			break;
		case 0x03://COLON+VD_D
			temp = temp | 0x04040000;
			break;
		default:break;
	}
	return temp;
}

/**
 * @LastEditTime: Do not edit
 * @Description: 
 * @return {}
 */
void VFD_Display_Write_Buff(void)
{
	static uint8_t i = 0;

	VFD_WRITE_BUFF[G1] = VFD_Show_Number_G1(bcd_to_decimal(g_tRTC.rtc_second), VFD_G1_PBC_EN, VFD_G1_MP3_CLR);

	if(sys_timer.System_500ms)
	{
        sys_timer.System_500ms = 0;
		i++;
		VFD_WRITE_BUFF[G2] = VFD_Show_Number_G2_G3(bcd_to_decimal(g_tRTC.rtc_minute), i, VFD_G2_DVD_CLR);
	}

	VFD_WRITE_BUFF[G3] = VFD_Show_Number_G2_G3(bcd_to_decimal(g_tRTC.rtc_hour), VFD_G3_CON_EN, VFD_G3_DOD_EN);

	VFD_WRITE_BUFF[G4] = VFD_Show_Number_G1(bcd_to_decimal(g_tRTC.rtc_second), VFD_G1_PBC_CLR, VFD_G1_MP3_CLR);

	if(sys_timer.System_Ticks % 500 == 0)
	{
		VFD_WRITE_BUFF[G5] = VFD_Show_Number_G1(bcd_to_decimal(g_tRTC.rtc_second), VFD_G1_PBC_CLR, VFD_G1_MP3_CLR);
	}
}

/**
 * @LastEditTime: Do not edit
 * @Description: 
 * @param {uint8_t} on_off
 * @return {}
 */
void VFD_Full(uint8_t on_off)
{
	if(on_off == VFD_GRID_OFF)
	{
		VFD_SendData(0x00000000);
	}
	else
	{
		VFD_SendData(0xFFFFFFFF);
	}
}

/**
 * @LastEditTime: Do not edit
 * @Description: 
 * @return {}
 */
void vfd_default(void)
{
	//EN上升沿时显示
	EN(DISABLE);
	//CLK上升沿数据输入
	CLK(DISABLE);
	DIN(VFD_GRID_OFF);
	
	VFD_WRITE_BUFF[G1] = VFD_Show_Number_G1((g_tRTC.rtc_second), VFD_G1_PBC_EN, VFD_G1_MP3_CLR);
	VFD_WRITE_BUFF[G2] = VFD_Show_Number_G2_G3((g_tRTC.rtc_minute), VFD_G2_CON_EN, VFD_G2_DVD_CLR);
	VFD_WRITE_BUFF[G3] = VFD_Show_Number_G2_G3((g_tRTC.rtc_hour), VFD_G3_CON_EN, VFD_G3_DOD_EN);
	VFD_WRITE_BUFF[G4] = VFD_Show_Number_G1((g_tRTC.rtc_second), VFD_G1_PBC_CLR, VFD_G1_MP3_CLR);
	VFD_WRITE_BUFF[G5] = VFD_Show_Number_G1((g_tRTC.rtc_second), VFD_G1_PBC_CLR, VFD_G1_MP3_CLR);
}

/**
 * @LastEditTime: Do not edit
 * @Description: 
 * @return {}
 */
void VFD_Display(void)
{
	uint8_t i;
	uint32_t disp;
	for(i = 0; i < 5; i++)
	{
		VFD_Display_Write_Buff();
		switch(i)
		{
			case 0://G1
				disp = VFD_WRITE_BUFF[G1] | ((uint32_t)0x01 << 31);
				break;
			case 1://G2
				disp = VFD_WRITE_BUFF[G2] | ((uint32_t)0x01 << 30);
				break;
			case 2://G3
				disp = VFD_WRITE_BUFF[G3] | ((uint32_t)0x01 << 29);
				break;
			case 3://G4
				disp = VFD_WRITE_BUFF[G4] | ((uint32_t)0x01 << 28);
				break;
			case 4://G5
				disp = VFD_WRITE_BUFF[G5] | ((uint32_t)0x01 << 27);
				break;
			default:disp = 0x00;
				break;
		}
		VFD_SendData(disp);
	}
}
